package org.fujene.memoryblock.local;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.fujene.constants.Constants;
import org.fujene.diskblock.DiskBlock;
import org.fujene.memoryblock.MemoryBlock;
import org.fujene.toolbox.ByteConverter;

public class LocalContentBlock extends MemoryBlock{
	private volatile int opt_length = 0;

	public LocalContentBlock(int bodySize, int ID, boolean isAllocate){
		super(bodySize, ID, Constants.MEMORY_TYPE_CONTENTS, isAllocate);
	}

	// 1個分の本文情報
	public class Contents{
		private int from = -1;
		private int strLength;
		private String content;

		// 情報読み出し
		public Contents(int from){
			this.from = from;
			this.strLength = ByteConverter.byteToInt(getBody(from, STRLEN));
			from += STRLEN;
			try{
				this.content = new String(getBody(from, this.strLength), "UTF-8");
			}
			catch(UnsupportedEncodingException e){}
		}

		// 読み出さない
		public Contents(int from, String str){
			set(from, str);
		}

		public void set(String str){
			this.content = str;
			try{
				this.strLength = str.getBytes("UTF-8").length;
			}
			catch(UnsupportedEncodingException e){}
		}

		public void set(int from, String str){
			this.from = from;
			set(str);
		}

		public void write(){
			// from が -1 だったら書き込まない
			if (this.from == -1) return;

			bodyVacancy -= STRLEN + strLength;
			opt_length++;
			int tmp = this.from;
			setBody(ByteConverter.intToByte(this.strLength, STRLEN), tmp);
			tmp += STRLEN;
			try{
				byte[] b = content.getBytes("UTF-8");
				setBody(b, tmp);
			}
			catch(UnsupportedEncodingException e){}
		}

		public void write(int from){
			this.from = from;
			write();
		}

		public String getContent(){
			return content;
		}
	}

	public String getContent(int ptr){
		Contents ptred = new Contents(ptr);
		return ptred.content;
	}

	public void setContent(int ptr, String str){
		Contents newContent = new Contents(ptr, str);
		newContent.write();
	}

	// サイズ確認なし
	public int getNewPointer(){
		return this.bodySize - this.bodyVacancy;
	}

	// サイズ確認つき
	public int getNewPointer(String str){
		try{
			if (this.bodyVacancy >= STRLEN + str.getBytes("UTF-8").length){
				return this.bodySize - this.bodyVacancy;
			}else{
				return -1;
			}
		}
		catch(UnsupportedEncodingException e){
			return -1;
		}
	}

	public int getCount(){
		return opt_length;
	}

	@Override
	public int getOptionSize(){
		return 1;
	}

	@Override
	public byte[] getOptionByteStream(){
		ByteArrayOutputStream stream = new ByteArrayOutputStream();

		try{
			stream.write(ByteConverter.intToByte(opt_length, 4));
		}
		catch(IOException e){}
		return stream.toByteArray();
	}

	@Override
	public int getOption(int num){
		switch(num){
		case 0:
			return opt_length;
		default:
			return 0;
		}
	}

	@Override
	public void setOption(int option, int value){
		if (option == 0) opt_length = value;
	}

	@Override
	public String getClassName(){
		return new String("ContentBlock");
	}

	@Override
	public byte[] getData() throws IOException{
		throw new NoSuchMethodError("Unimplemented method");
	}

	@Override
	public void setData(byte[] array) throws IOException{
		throw new NoSuchMethodError("Unimplemented method");
	}

	@Override
	public DiskBlock toDisk(int from, int to, String dir){
		return null;
	}
}
